package com.hq.common.utils;

import org.springframework.jdbc.core.JdbcTemplate;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * Created with IntelliJ IDEA.
 * User: GEOMETRY
 * Date: 15-7-1
 * Time: 下午3:01
 * To change this template use File | Settings | File Templates.
 */
public class BeanUtil {

    public static JdbcTemplate jdbcTemplate;

    public static List<Map<String,Object>> getColumnsByTableName(String tableName){
        String sql="select table_name,column_name,data_type from information_schema.columns where table_name =?  and table_schema='r20xp1y8j9j044xn'";
        return  getJdbcTemplate().queryForList(sql, tableName.toUpperCase());
    }

    public static void createDomain(String domainName,String packageName,List<Map<String,Object>> columnList,String path){
        StringBuffer domainString=new StringBuffer("package "+packageName).append(".domain;").append("\n");
        StringBuffer gster=new StringBuffer();
        domainString.append("public class ").append(domainName).append("\n");
        domainString.append("{").append("\n");
        String fieldName;
        String fieldType;
        for(Map<String,Object> colMap:columnList){
            fieldName=parseColumn(colMap.get("COLUMN_NAME").toString());
            fieldType=parseColumnType(colMap.get("DATA_TYPE").toString());
            domainString.append("    private ").append(fieldType).append(" ").append(fieldName).append(";\n");

            gster.append("    public void set").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("(").append(fieldType).append(" ").append(fieldName).append(")").append("\n");
            gster.append("    {").append("\n");
            gster.append("        this.").append(fieldName).append("=").append(fieldName).append(";").append("\n");
            gster.append("    }").append("\n");
            gster.append("\n");
            gster.append("    public ").append(fieldType).append(" get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("()").append("\n");
            gster.append("    {").append("\n");
            gster.append("        return this.").append(fieldName).append(";").append("\n");
            gster.append("    }").append("\n");
        }
        domainString.append("\n");
        domainString.append(gster);
        domainString.append("}").append("\n");
//        System.out.println("=============================");
//        System.out.println(domainString.toString());
        write(path,domainName+".java",domainString);
    }

    public static void createDao(String domainName,String packageName,List<Map<String,Object>> columnList,String path){
        StringBuffer daoString=new StringBuffer("package "+packageName).append(".dao;").append("\n");
        daoString.append("import org.apache.commons.lang.StringUtils;\n");
        daoString.append("import org.springframework.beans.factory.annotation.Autowired;\n");
        daoString.append("import org.springframework.jdbc.core.JdbcTemplate;\n");
        daoString.append("import org.springframework.stereotype.Repository;\n");
        daoString.append("import org.springframework.jdbc.core.RowMapper;\n");
        daoString.append("import com.hq.ti.domain.BaseObject;\n");
        daoString.append("import "+packageName+"."+domainName+";\n");
        daoString.append("import java.sql.ResultSet;\n");
        daoString.append("import java.util.ArrayList;\n");
        daoString.append("import java.sql.SQLException;\n");
        daoString.append("import java.util.List;\n");
        daoString.append("import java.util.Map;\n");
        daoString.append("@Repository\n");
        daoString.append("public class ").append(domainName).append("Dao extends BaseObject\n");
        daoString.append("{").append("\n");

        daoString.append("@Autowired").append("\n");
        daoString.append("private JdbcTemplate jdbcTemplate;").append("\n");
        daoString.append("public JdbcTemplate getJdbcTemplate() {").append("\n");
        daoString.append("    return jdbcTemplate;").append("\n");
        daoString.append("}").append("\n");

        /*insert*/
        String dname=domainName.substring(0,1).toLowerCase()+domainName.substring(1);
        daoString.append("  public void insert(").append(domainName).append(" ").append(dname).append(")").append("\n");
        daoString.append("  {").append("\n");
        daoString.append("      String sql=\"insert into ").append(columnList.get(0).get("TABLE_NAME")).append("(");
        StringBuffer insertCol=new StringBuffer();
        StringBuffer insertValue=new StringBuffer();
        StringBuffer update=new StringBuffer();
        StringBuffer query=new StringBuffer();
        StringBuffer rowMapperStr=new StringBuffer();
        StringBuffer args=new StringBuffer("Object[] args=new Object[]{");
        String fieldName;
        for(Map<String,Object> colMap:columnList){
            insertCol.append(colMap.get("COLUMN_NAME")).append(",");
            insertValue.append("?,");
            fieldName=parseColumn(colMap.get("COLUMN_NAME").toString());
            args.append(dname).append(".get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("(),");

            query.append("      if(StringUtils.isNotEmpty(").append(dname).append(".get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("()))\n");
            query.append("      {\n");
            query.append("          sql.append(\" and ").append(colMap.get("COLUMN_NAME").toString()).append("=? \");\n");
            query.append("          argList.add(").append(dname).append(".get").append(fieldName.substring(0, 1).toUpperCase()).append(fieldName.substring(1)).append("());\n");
            query.append("      }\n");


            update.append("      if(StringUtils.isNotEmpty(").append(dname).append(".get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("()))\n");
            update.append("      {\n");
            update.append("         sql.append(\" ").append(colMap.get("COLUMN_NAME").toString()).append("=?, \");\n");
            update.append("         argList.add(").append(dname).append(".get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("());\n");
            update.append("      }\n");

            rowMapperStr.append("   ").append(dname).append("Tmp.set").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("(rs.getString(\""+colMap.get("COLUMN_NAME").toString()+"\"));\n");
        }
        insertCol.deleteCharAt(insertCol.length()-1);
        insertValue.deleteCharAt(insertValue.length()-1);
//        update.deleteCharAt(update.length()-1);
        args.deleteCharAt(args.length()-1).append("};\n");
        daoString.append(insertCol).append(") values(").append(insertValue).append(")\";\n");
        daoString.append(args).append("\n");
        daoString.append(" getJdbcTemplate().update(sql,args);").append("\n");
        daoString.append("  }").append("\n");

//        daoString.append("  public List<Map<String,Object>>  query(").append(domainName).append(" ").append(dname).append(")").append("\n");
//        daoString.append("  {").append("\n");
//        daoString.append("      StringBuffer sql=new StringBuffer(\"select ").append(insertCol).append(" from ").append(columnList.get(0).get("TABLE_NAME")).append(" where 1=1 \");\n");
//        daoString.append("      List<Object> argList=new ArrayList<Object>();\n");
//        daoString.append(query.toString());
//        daoString.append("      return getJdbcTemplate().queryForList(sql.toString(),argList.toArray(new Object[]{}));").append("\n");
//        daoString.append("  }").append("\n");


        daoString.append("  public List<"+domainName+">  query(").append(domainName).append(" ").append(dname).append(")").append("\n");
        daoString.append("  {").append("\n");
        daoString.append("      StringBuffer sql=new StringBuffer(\"select ").append(insertCol).append(" from ").append(columnList.get(0).get("TABLE_NAME")).append(" where 1=1 \");\n");
        daoString.append("      List<Object> argList=new ArrayList<Object>();\n");
        daoString.append(query.toString());
        daoString.append("      return getJdbcTemplate().query(sql.toString(),argList.toArray(new Object[]{}),new RowMapper<"+domainName+">()").append("{\n");
        daoString.append("          public " + domainName + " mapRow(ResultSet rs, int rowNum) throws SQLException {\n");
        daoString.append("              ").append(domainName).append(" ").append(dname).append("Tmp=new ").append(domainName).append("();\n");
        daoString.append(rowMapperStr);
        daoString.append("              return ").append(dname).append("Tmp;\n");
        daoString.append("          }\n");
        daoString.append("          }\n");
        daoString.append("      );").append("\n");
        daoString.append("  }").append("\n");

        daoString.append("  public void update(").append(domainName).append(" ").append(dname).append(")").append("\n");
        daoString.append("  {").append("\n");
        daoString.append("      StringBuffer sql=new StringBuffer(\"update ").append(columnList.get(0).get("TABLE_NAME")).append(" set \");\n");
        daoString.append("      List<Object> argList=new ArrayList<Object>();\n");
        daoString.append(update.toString()).append(" \n");
        daoString.append("      sql.append(\" where oid = ?\");\n");
        daoString.append("      getJdbcTemplate().update(sql.toString(),argList.toArray(new Object[]{}));").append("\n");
        daoString.append("  }").append("\n");

        daoString.append("}").append("\n");
//        System.out.println("=============================");
//        System.out.println(daoString.toString());

        write(path,domainName+"Dao.java",daoString);
    }

    public static void createService(String domainName,String packageName,List<Map<String,Object>> columnList,String path){
        StringBuffer serviceString=new StringBuffer("package "+packageName).append(".service;").append("\n");
        serviceString.append("import org.apache.commons.lang.StringUtils;\n");
        serviceString.append("import org.springframework.beans.factory.annotation.Autowired;\n");
        serviceString.append("import com.hq.ti.domain.BaseObject;\n");
        serviceString.append("import org.springframework.stereotype.Service;\n");
        serviceString.append("import java.util.List;\n");
        serviceString.append("import "+packageName+"."+domainName+";\n");
        serviceString.append("@Service\n");
        serviceString.append("public class ").append(domainName).append("Service extends BaseObject{\n");
        String dname=domainName.substring(0,1).toLowerCase()+domainName.substring(1);

        serviceString.append("@Autowired").append("\n");
        serviceString.append("  private "+domainName+"Dao "+dname+"Dao;").append("\n");
        serviceString.append("  private "+domainName+"Dao get"+domainName+"() {").append("\n");
        serviceString.append("    return "+dname+"Dao;").append("\n");
        serviceString.append("  }").append("\n");

        serviceString.append("  public void insert("+domainName+" "+dname+"){\n");
        serviceString.append("      ").append(dname).append("Dao.insert("+dname+");\n");
        serviceString.append("  };\n");

        serviceString.append("  public void update("+domainName+" "+dname+"){\n");
        serviceString.append("      ").append(dname).append("Dao.update("+dname+");\n");
        serviceString.append("  };\n");

        serviceString.append("  public List<"+domainName+"> query("+domainName+" "+dname+"){\n");
        serviceString.append("      return ").append(dname).append("Dao.query("+dname+");\n");
        serviceString.append("  };\n");
        serviceString.append("}\n");

        write(path,domainName+"Service.java",serviceString);
    }

    public static void create(String tableName,String domainName,String packageName,String path){
        List<Map<String,Object>> columnList=getColumnsByTableName(tableName);
        createDomain(domainName,packageName,columnList,path);
        createDao(domainName,packageName,columnList,path);
        createService(domainName,packageName,columnList,path);
    }

    public static JdbcTemplate getJdbcTemplate() {
        return ApplicationContextUtils.getBean("jdbcTemplate");
    }

    public static String parseColumn(String column){
        String[] cols= column.split("_");
        StringBuffer field=new StringBuffer();
        for(String col:cols){
            if(field.length()==0){
                field.append(col.toLowerCase());
            }else {
                field.append(col.substring(0,1).toUpperCase()).append(col.substring(1).toLowerCase());
            }
        }
        return field.toString();
    }

    public static String parseColumnType(String dataType){
        if("LONG".equals(dataType.toUpperCase())||"INT".equals(dataType.toUpperCase())){
            return "Long";
        }else if("NUMBER".equals(dataType.toUpperCase())||"DOUBLE".equals(dataType.toUpperCase())){
            return "Double";
        }else if("datetime".equals(dataType.toLowerCase())){
            return "Date";
        }else {
            return "String";
        }
    }

    public static void write(String path,String fileName,StringBuffer content){
        try {
        File file=new File(path+fileName);
        if(!file.exists()){
            file.createNewFile();
        }
            FileOutputStream fos=new FileOutputStream(file);
            fos.write(content.toString().getBytes("UTF-8"));
        } catch (IOException e) {
            e.printStackTrace();  //To change body of catch statement use File | Settings | File Templates.
        }
    }


    public static void createHiDomain(String domainName,String packageName,List<Map<String,Object>> columnList,String path){
        StringBuffer domainString=new StringBuffer("package "+packageName).append(".domain;").append("\n");
        domainString.append("import javax.persistence.*;\n");
        domainString.append("import java.util.Date;\n");
        StringBuffer gster=new StringBuffer();
        domainString.append("\n" +
                "@Entity\n" +
                "@Table(name=\""+columnList.get(0).get("table_name")+"\")\n");
        domainString.append("public class ").append(domainName).append("\n");
        domainString.append("{").append("\n");
        String fieldName;
        String fieldType;
        for(Map<String,Object> colMap:columnList){
            fieldName=parseColumn(colMap.get("COLUMN_NAME").toString());
            fieldType=parseColumnType(colMap.get("DATA_TYPE").toString());
            if("id".equals(fieldName.toLowerCase())||"oid".equals(fieldName.toLowerCase())){
                domainString.append("    @Id\n");
                domainString.append("    @GeneratedValue(strategy=GenerationType.IDENTITY)\n");
            }
            domainString.append("    @Column(name=\""+colMap.get("COLUMN_NAME").toString()+"\")\n");
            domainString.append("    private ").append(fieldType).append(" ").append(fieldName).append(";\n");

            gster.append("    public void set").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("(").append(fieldType).append(" ").append(fieldName).append(")").append("\n");
            gster.append("    {").append("\n");
            gster.append("        this.").append(fieldName).append("=").append(fieldName).append(";").append("\n");
            gster.append("    }").append("\n");
            gster.append("\n");
            gster.append("    public ").append(fieldType).append(" get").append(fieldName.substring(0,1).toUpperCase()).append(fieldName.substring(1)).append("()").append("\n");
            gster.append("    {").append("\n");
            gster.append("        return this.").append(fieldName).append(";").append("\n");
            gster.append("    }").append("\n");
        }
        domainString.append("\n");
        domainString.append(gster);
        domainString.append("}").append("\n");
//        System.out.println("=============================");
//        System.out.println(domainString.toString());
        write(path,domainName+".java",domainString);
    }

    public static void createHiDao(String domainName,String packageName,List<Map<String,Object>> columnList,String path) {
        StringBuffer daoString = new StringBuffer("package " + packageName).append(".dao;").append("\n");
        daoString.append("import org.springframework.stereotype.Repository;\n");
        daoString.append("import com.hq.base.dao.BaseDAO;\n");
        daoString.append("import " + packageName + ".domain." + domainName + ";\n");
        daoString.append("@Repository\n");
        daoString.append("public class ").append(domainName).append("Dao extends BaseDAO<" + domainName + ">\n");
        daoString.append("{").append("\n");
        daoString.append("}");
        write(path, domainName + "Dao.java", daoString);
    }


    public static void createHiService(String domainName,String packageName,List<Map<String,Object>> columnList,String path) {
        StringBuffer serviceString = new StringBuffer("package " + packageName).append(".service;").append("\n");
        serviceString.append("import org.springframework.beans.factory.annotation.Autowired;\n");
        serviceString.append("import com.hq.base.domain.BaseObject;\n");
        serviceString.append("import org.springframework.stereotype.Service;\n");
        serviceString.append("import java.util.List;\n");
        serviceString.append("import " + packageName + ".domain." + domainName + ";\n");
        serviceString.append("import " + packageName + ".dao." + domainName + "Dao;\n");
        serviceString.append("@Service\n");
        serviceString.append("public class ").append(domainName).append("Service extends BaseObject{\n");
        String dname = domainName.substring(0, 1).toLowerCase() + domainName.substring(1);

        serviceString.append("@Autowired").append("\n");
        serviceString.append("  private " + domainName + "Dao " + dname + "Dao;").append("\n");
        serviceString.append("  private " + domainName + "Dao get" + domainName + "Dao() {").append("\n");
        serviceString.append("    return " + dname + "Dao;").append("\n");
        serviceString.append("  }").append("\n");

        serviceString.append("  public " + domainName + " get" + domainName + "(Long id) {").append("\n");
        serviceString.append("    return get" + domainName + "Dao().get(id);").append("\n");
        serviceString.append("  }").append("\n");

        serviceString.append("  public List<" + domainName + "> get" + domainName + "("+domainName+" "+dname+" ) {").append("\n");
        serviceString.append("    return get" + domainName + "Dao().get("+dname+");").append("\n");
        serviceString.append("  }").append("\n");

        serviceString.append("  public void saveOrUpdate("+domainName+" domain) {").append("\n");
        serviceString.append("     get" + domainName + "Dao().saveOrUpdate(domain);").append("\n");
        serviceString.append("  }").append("\n");

        serviceString.append("}");

        write(path, domainName + "Service.java", serviceString);
    }

    public static void createHi(String tableName,String domainName,String packageName,String path){
        List<Map<String,Object>> columnList=getColumnsByTableName(tableName);
        createHiDomain(domainName,packageName,columnList,path);
        createHiDao(domainName,packageName,columnList,path);
        createHiService(domainName,packageName,columnList,path);
    }
}
